home *** CD-ROM | disk | FTP | other *** search
/ QRZ! Ham Radio 8 / QRZ Ham Radio Callsign Database - Volume 8.iso / pc / files / t_unix / j109lxa4.tar / rip.c < prev    next >
C/C++ Source or Header  |  1994-06-04  |  17KB  |  697 lines

  1. /* This file contains code to implement the Routing Information Protocol (RIP)
  2.  * and is derived from 4.2BSD code. Mike Karels of Berkeley has stated on
  3.  * TCP-IP that the code may be freely used as long as UC Berkeley is
  4.  * credited. (Well, here's some credit :-). AGB 4-28-88
  5.  
  6.  * Further documentation on the RIP protocol is now available in Charles
  7.  * Hedrick's draft RFC, as yet unnumbered. AGB 5-6-88
  8.  *
  9.  * The RIP RFC has now been issued as RFC1058. AGB 7-23-88
  10.  *
  11.  * Code gutted and substantially rewritten. KA9Q 9/89
  12.  *
  13.  * Mods by PA0GRI
  14.  */
  15. #include "global.h"
  16. #include "config.h"
  17. #include "mbuf.h"
  18. #include "netuser.h"
  19. #include "udp.h"
  20. #include "timer.h"
  21. #include "iface.h"
  22. #include "ip.h"
  23. #include "internet.h"
  24. #include "rip.h"
  25. #include "arp.h"
  26.  
  27. #ifdef RIP
  28.  
  29. struct rip_stat Rip_stat;
  30. int16 Rip_trace;
  31. int Rip_merge;
  32. int32 Rip_ttl = RIP_TTL;
  33. struct rip_list *Rip_list;
  34. struct udp_cb *Rip_cb;
  35.  
  36. struct rip_refuse *Rip_refuse;
  37.  
  38. static void rip_rx __ARGS((struct iface *iface,struct udp_cb *sock,int cnt));
  39. static void proc_rip __ARGS((struct iface *iface,int32 gateway,
  40.     struct rip_route *ep));
  41. static char *putheader __ARGS((char *cp,char command,char version));
  42. static char *putentry __ARGS((char *cp,int16 fam,int32 target,int32 metric));
  43. static void send_routes __ARGS((int32 dest,int16 port,int split,int trig,
  44.     int us));
  45.  
  46. /* Send RIP CMD_RESPONSE packet(s) to the specified rip_list entry */
  47. void
  48. rip_shout(p)
  49. void *p;
  50. {
  51.     register struct rip_list *rl;
  52.  
  53.     rl = (struct rip_list *)p;
  54.     stop_timer(&rl->rip_time);
  55.     send_routes(rl->dest,RIP_PORT,(rl->flags & RIP_SPLIT),0,
  56.         rl->flags & RIP_US);
  57.     set_timer(&rl->rip_time,rl->interval*1000L);
  58.     start_timer(&rl->rip_time);
  59. }
  60.  
  61. /* Send the routing table. */
  62. static void
  63. send_routes(dest,port,split,trig,us)
  64. int32 dest;             /* IP destination address to send to */
  65. int16 port;
  66. int split;              /* Do split horizon? */
  67. int trig;               /* Send only triggered updates? */
  68. int us;                 /* Include our address in update */
  69. {
  70.     char *cp;
  71.     int i,bits,numroutes,maxroutes;
  72.     int16 pktsize;
  73.     struct mbuf *bp;
  74.     struct route *rp;
  75.     struct socket lsock,fsock;
  76.     struct iface *iface;
  77.  
  78.     if((rp = rt_lookup(dest)) == NULLROUTE)
  79.         return; /* No route exists, can't do it */
  80.     iface = rp->iface;
  81.  
  82.     /* Compute maximum packet size and number of routes we can send */
  83.     pktsize = ip_mtu(dest) - IPLEN;
  84.     pktsize = min(pktsize,MAXRIPPACKET);
  85.     maxroutes = (pktsize - RIPHEADER) / RIPROUTE;
  86.  
  87.     lsock.address = INADDR_ANY;
  88.     lsock.port = RIP_PORT;
  89.     fsock.address = dest;
  90.     fsock.port = port;
  91.  
  92.     /* Allocate space for a full size RIP packet and generate header */
  93.     if((bp = alloc_mbuf(pktsize)) == NULLBUF)
  94.         return; 
  95.     numroutes = 0;
  96.     cp = putheader(bp->data,RIPCMD_RESPONSE,RIPVERSION);
  97.  
  98.        /* Emit route to ourselves, if requested */
  99.        if(us){
  100.            cp = putentry(cp,RIP_IPFAM,iface->addr,0);
  101.            numroutes++;
  102.        }
  103.  
  104.     /* Emit default route, if appropriate */
  105.     if(R_default.iface != NULLIF && !(R_default.flags & RTPRIVATE)
  106.      && (!trig || (R_default.flags & RTTRIG))){
  107.         if(!split || iface != R_default.iface){
  108.             cp = putentry(cp,RIP_IPFAM,0,R_default.metric);
  109.             numroutes++;
  110.         } else if(trig){
  111.             cp = putentry(cp,RIP_IPFAM,0,RIP_INFINITY);
  112.             numroutes++;
  113.         }
  114.     }
  115.     for(bits=0;bits<32;bits++){
  116.         for(i=0;i<HASHMOD;i++){
  117.             for(rp = Routes[bits][i];rp != NULLROUTE;rp=rp->next){
  118.                 if((rp->flags & RTPRIVATE)
  119.                  || (trig && !(rp->flags & RTTRIG))) 
  120.                     continue;
  121.  
  122.                 if(numroutes >= maxroutes){
  123.                     /* Packet full, flush and make another */
  124.                     bp->cnt = RIPHEADER + numroutes * RIPROUTE;
  125.                     send_udp(&lsock,&fsock,0,0,bp,bp->cnt,0,0);
  126.                     Rip_stat.output++;
  127.                     if((bp = alloc_mbuf(pktsize)) == NULLBUF)
  128.                         return; 
  129.                     numroutes = 0;
  130.                     cp = putheader(bp->data,RIPCMD_RESPONSE,RIPVERSION);
  131.                 }
  132.                 if(!split || iface != rp->iface){
  133.                     cp = putentry(cp,RIP_IPFAM,rp->target,rp->metric);
  134.                     numroutes++;
  135.                 } else if(trig){
  136.                     cp = putentry(cp,RIP_IPFAM,rp->target,RIP_INFINITY);
  137.                     numroutes++;
  138.                 }
  139.             }
  140.         }
  141.     }
  142.     if(numroutes != 0){
  143.         bp->cnt = RIPHEADER + numroutes * RIPROUTE;
  144.         send_udp(&lsock,&fsock,0,0,bp,bp->cnt,0,0);
  145.         Rip_stat.output++;
  146.     } else {
  147.         free_p(bp);
  148.     }
  149. }
  150. /* Add an entry to the rip broadcast list */
  151. int
  152. rip_add(dest,interval,flags)
  153. int32 dest;
  154. int32 interval;
  155. char flags;
  156. {
  157.     register struct rip_list *rl;
  158.     struct route *rp;
  159.  
  160.     for(rl = Rip_list; rl != NULLRL; rl = rl->next)
  161.         if(rl->dest == dest)
  162.             return 0;
  163.  
  164.     if((rp = rt_lookup(dest)) == NULLROUTE){
  165.         tprintf("%s is unreachable\n",inet_ntoa(dest));
  166.         return 1;
  167.     }
  168.     /* get a chunk of memory for the rip interface descriptor */
  169.     rl = (struct rip_list *)callocw(1,sizeof(struct rip_list));
  170.  
  171.     /* tack this record on as the first in the list */
  172.     rl->next = Rip_list;
  173.     if(rl->next != NULLRL)
  174.         rl->next->prev = rl;
  175.     Rip_list = rl;
  176.  
  177.     rl->dest = dest;
  178.  
  179.     /* and the interface ptr, tick interval and flags */
  180.     rl->iface = rp->iface;
  181.     rl->interval = interval;
  182.     rl->flags = flags;
  183.  
  184.     /* and set up the timer stuff */
  185.     set_timer(&rl->rip_time,interval*1000L);
  186.     rl->rip_time.func = rip_shout;
  187.     rl->rip_time.arg = rl;
  188.     start_timer(&rl->rip_time);
  189.     return 0;
  190. }
  191.  
  192. /* add a gateway to the rip_refuse list which allows us to ignore their
  193.  * advertisements
  194. */
  195. int
  196. riprefadd(gateway)
  197. int32 gateway;
  198. {
  199.     register struct rip_refuse *rl;
  200.  
  201.     for(rl = Rip_refuse; rl != NULLREF; rl = rl->next)
  202.         if(rl->target == gateway)
  203.             return 0;       /* Already in table */
  204.   
  205.  
  206.     /* get a chunk of memory for the rip interface descriptor */
  207.     rl = (struct rip_refuse *)callocw(1,sizeof(struct rip_refuse));
  208.  
  209.     /* tack this record on as the first in the list */
  210.     rl->next = Rip_refuse;
  211.     if(rl->next != NULLREF)
  212.         rl->next->prev = rl;
  213.     Rip_refuse = rl;
  214.  
  215.     /* fill in the gateway to ignore */
  216.     rl->target = gateway;
  217.     return 0;
  218. }
  219.  
  220. /* drop a RIP target */
  221. int
  222. rip_drop(dest)
  223. int32   dest;
  224. {
  225.     register struct rip_list *rl;
  226.  
  227.     for(rl = Rip_list; rl != NULLRL; rl = rl->next)
  228.         if(rl->dest == dest)
  229.             break;
  230.  
  231.     /* leave if we didn't find it */
  232.     if(rl == NULLRL)
  233.         return 0;
  234.  
  235.     /* stop the timer */
  236.     stop_timer(&rl->rip_time);
  237.  
  238.     /* Unlink from list */
  239.     if(rl->next != NULLRL)
  240.         rl->next->prev = rl->prev;
  241.     if(rl->prev != NULLRL)
  242.         rl->prev->next = rl->next;
  243.     else
  244.         Rip_list = rl->next;
  245.  
  246.     /* and deallocate the descriptor memory */
  247.     free((char *)rl);
  248.     return 0;
  249. }
  250.  
  251. /* drop a RIP-refuse target from the rip_refuse list */
  252. int
  253. riprefdrop(gateway)
  254. int32 gateway;
  255. {
  256.     register struct rip_refuse *rl;
  257.     
  258.     for(rl = Rip_refuse; rl != NULLREF; rl = rl->next)
  259.         if(rl->target == gateway)
  260.             break;
  261.   
  262.     /* leave if we didn't find it */
  263.     if(rl == NULLREF)
  264.         return 0;
  265.  
  266.     /* Unlink from list */
  267.     if(rl->next != NULLREF)
  268.         rl->next->prev = rl->prev;
  269.     if(rl->prev != NULLREF)
  270.         rl->prev->next = rl->next;
  271.     else
  272.         Rip_refuse = rl->next;
  273.  
  274.     /* and deallocate the structure memory */
  275.     free((char *)rl);
  276.     return 0;
  277. }
  278.  
  279. /* function to output a RIP CMD_RESPONSE packet for the rip_trigger list */
  280. void
  281. rip_trigger()
  282. {
  283.     register struct rip_list *rl;
  284.     int bits,i;
  285.     struct route *rp;
  286.  
  287.     for(rl=Rip_list;rl != NULLRL;rl = rl->next){
  288.         send_routes(rl->dest,RIP_PORT,(rl->flags & RIP_SPLIT),1,0);
  289.     }
  290.     /* Clear the trigger list */
  291.     R_default.flags &= ~RTTRIG;
  292.     for(bits=0;bits<32;bits++){
  293.         for(i=0;i<HASHMOD;i++){
  294.             for(rp = Routes[bits][i];rp != NULLROUTE;rp = rp->next){
  295.                 rp->flags &= ~RTTRIG;
  296.             }
  297.         }
  298.     }
  299. }
  300.  
  301. /* Start RIP agent listening at local RIP UDP port */
  302. int
  303. rip_init()
  304. {
  305.     struct socket lsock;
  306.  
  307.     lsock.address = INADDR_ANY;
  308.     lsock.port = RIP_PORT;
  309.  
  310.     if(Rip_cb == NULLUDP)
  311.         Rip_cb = open_udp(&lsock,rip_rx);
  312.  
  313.     return 0;
  314. }
  315.  
  316. /* Process RIP input received from 'interface'. */
  317. static void
  318. rip_rx(iface,sock,cnt)
  319. struct iface *iface;
  320. struct udp_cb *sock;
  321. int cnt;
  322. {
  323.     struct mbuf *bp;
  324.     struct socket fsock;
  325.     int cmd;
  326.     register struct rip_refuse *rfl;
  327.     struct rip_route entry;
  328.     struct route *rp;
  329.  
  330.     /* receive the RIP packet */
  331.     recv_udp(sock,&fsock,&bp);
  332.  
  333.     /* increment the rcvd cnt */
  334.     Rip_stat.rcvd++;
  335.  
  336.     /* check the gateway of this packet against the rip_refuse list and
  337.      * discard it if a match is found
  338.      */
  339.     for(rfl=Rip_refuse;rfl != NULLREF;rfl = rfl->next){
  340.         if(fsock.address == rfl->target){
  341.             Rip_stat.refusals++;
  342.             if(Rip_trace > 1)
  343.                 printf("RIP refused from %s\n",
  344.                  inet_ntoa(fsock.address));
  345.             free_p(bp);
  346.             return;
  347.          }
  348.     }
  349.     cmd = PULLCHAR(&bp);
  350.     /* Check the version of the frame */
  351.     if(PULLCHAR(&bp) != RIPVERSION){
  352.         free_p(bp);
  353.         Rip_stat.version++;
  354.         return;
  355.     }
  356.     switch(cmd){
  357.     case RIPCMD_RESPONSE:
  358.         if(Rip_trace > 1)
  359.             printf("RIPCMD_RESPONSE from %s \n",inet_ntoa(fsock.address));
  360.  
  361.         Rip_stat.response++;
  362.         (void)pull16(&bp);      /* remove one word of padding */
  363.         while(len_p(bp) >= RIPROUTE){
  364.             pullentry(&entry,&bp);
  365.             proc_rip(iface,fsock.address,&entry);
  366.         }
  367.         /* If we can't reach the sender of this update, or if
  368.          * our existing route is not through the interface we
  369.          * got this update on, add him as a host specific entry
  370.          */
  371.         if((rp = rt_blookup(fsock.address,32)) != NULLROUTE){
  372.             /* Host-specific route already exists, refresh it */
  373.             start_timer(&rp->timer);
  374.         } else if((rp = rt_lookup(fsock.address)) == NULLROUTE
  375.          || rp->iface != iface){
  376.             entry.addr_fam = RIP_IPFAM;
  377.             entry.target = fsock.address;
  378.             entry.metric = 0; /* will get incremented to 1 */
  379.             proc_rip(iface,fsock.address,&entry);
  380.         }
  381.         if(Rip_merge)
  382.             rt_merge(Rip_trace);
  383.         rip_trigger();
  384.         break;
  385.     case RIPCMD_REQUEST:
  386.         if(Rip_trace > 1)
  387.             printf("RIPCMD_REQUEST\n");
  388.  
  389.         Rip_stat.request++;
  390.         /* For now, just send the whole table with split horizon
  391.          * enabled when the source port is RIP_PORT, and send
  392.          * the whole table with split horizon disable when another
  393.          * source port is used. This should be replaced with a more
  394.          * complete implementation that checks for non-global requests
  395.          */
  396.         if(fsock.port == RIP_PORT)
  397.             send_routes(fsock.address,fsock.port,1,0,1);
  398.         else
  399.             send_routes(fsock.address,fsock.port,0,0,1);
  400.         break;
  401.     default:
  402.         if(Rip_trace > 1)
  403.             printf("RIPCMD: Unknown Type\n");
  404.  
  405.         Rip_stat.unknown++;
  406.         break;
  407.     } /* switch */
  408.     free_p(bp);
  409. }
  410. /* Apply a set of heuristics for determining the number of significant bits
  411.  * (i.e., the address mask) in the target address. Needed since RIP doesn't
  412.  * include the address mask for each entry.
  413.  */
  414. int
  415. nbits(target)
  416. int32 target;
  417. {
  418.     int bits;
  419.  
  420.     if(target == 0)
  421.         return 0;       /* Special case: 0.0.0.0 is the default route */
  422.  
  423.     /* Check the host-part bytes of
  424.      * the address to check for byte-wide zeros
  425.      * which we'll consider to be subnet routes.
  426.      * e.g. 44.80.0.0 will be considered to be equal to 44.80/16
  427.      * whereas 44.80.1.0 will be considered to be 44.80.1/24
  428.      */
  429. #ifdef __GNUC__
  430.     bits = 0;        /* suppress warning */
  431. #endif
  432.     switch (hibyte(hiword(target)) >> 6) {
  433.     case 3: /* Class C address */
  434.         /*is it a host address ? i.e. are there any 1's in the
  435.          * host part ?
  436.          */
  437.         if(target & 0xff)
  438.             bits = 32;
  439.         else
  440.             bits = 24;
  441.         break;
  442.     case 2:  /* Class B address */
  443.         if(target & 0xff)
  444.             bits = 32;
  445.         else if(target & 0xff00)
  446.             bits = 24;
  447.         else
  448.             bits = 16;
  449.         break;
  450.     case 0:   /* Class A address */
  451.     case 1:
  452.         if(target & 0xff)
  453.             bits = 32;
  454.         else if(target & 0xff00)
  455.             bits = 24;
  456.         else if(target & 0xff0000)
  457.             bits = 16;
  458.         else
  459.             bits = 8;
  460.     }
  461.  
  462.     return bits;
  463. }
  464. /* Remove and process a RIP response entry from a packet */
  465. static void
  466. proc_rip(iface,gateway,ep)
  467. struct iface *iface;
  468. int32 gateway;
  469. register struct rip_route *ep;
  470. {
  471.     int32 interval;
  472.     unsigned int bits;
  473.     register struct route *rp;
  474.     struct rip_list *rl;
  475.     int add = 0;    /* action flags */
  476.     int drop = 0;
  477.     int trigger = 0;
  478.  
  479.     if(ep->addr_fam != RIP_IPFAM) {
  480.         /* Skip non-IP addresses */
  481.         if(Rip_trace > 1)
  482.             printf("RIP_rx: Not an IP RIP packet !\n");
  483.         Rip_stat.addr_family++;
  484.         return;
  485.     }
  486.     /* Guess at the mask, since it's not explicit */
  487.     bits = nbits(ep->target);
  488.  
  489.     /* Don't ever add a route to myself through somebody! */
  490.     if(bits == 32 && ismyaddr(ep->target) != NULLIF){
  491.         if(Rip_trace > 1){
  492.             printf("route to self: %s %ld\n",
  493.              inet_ntoa(ep->target),ep->metric);
  494.         }
  495.         return;
  496.     }
  497.     /* Update metric to reflect link cost */
  498.     ep->metric++;
  499.     ep->metric = min(ep->metric,RIP_INFINITY);
  500.  
  501.     /* Find existing entry, if any */
  502.     rp = rt_blookup(ep->target,bits);
  503.  
  504.     /* Don't touch private routes */
  505.     if(rp != NULLROUTE && (rp->flags & RTPRIVATE))
  506.         return;
  507.  
  508.     if(rp == NULLROUTE){
  509.         if(ep->metric < RIP_INFINITY){
  510.             /* New route; add it and trigger an update */
  511.             add++;
  512.             trigger++;
  513.         }
  514.     } else if(rp->metric == RIP_INFINITY){
  515.         /* Route is in hold-down; ignore this guy */
  516.         if(Rip_trace > 0){
  517.             printf("ignored (hold-down): %s %lu\n",
  518.              inet_ntoa(ep->target),ep->metric);
  519.         }
  520.     } else if(rp->gateway == gateway && rp->iface == iface){
  521.         /* This is the gateway for the entry we already have;
  522.          * restart the timer
  523.          */
  524.         start_timer(&rp->timer);
  525.         if(rp->metric != ep->metric){
  526.             /* Metric has changed. Update it and trigger an
  527.              * update. If route has become unavailable, start
  528.              * the hold-down timeout.
  529.              */
  530.             if(Rip_trace){
  531.                 printf("metric change: %s %lu -> %lu\n",
  532.                  inet_ntoa(ep->target),rp->metric,ep->metric);
  533.             }
  534.             if(ep->metric == RIP_INFINITY)
  535.                 rt_timeout(rp); /* Enter hold-down timeout */
  536.             else
  537.                 rp->metric = ep->metric;
  538.             trigger++;
  539.         }
  540.     } else {
  541.         /* Entry is from a different gateway than the current route */
  542.         if(ep->metric < rp->metric){
  543.             /* Switch to a new gateway */
  544.             if(Rip_trace > 0){
  545.                 printf("metric better: %s %lu\n",
  546.                  inet_ntoa(ep->target),ep->metric);
  547.             }
  548.             drop++;
  549.             add++;
  550.             trigger++;
  551.         } else {
  552.             /* Metric is no better, stay with current route */
  553.             if(Rip_trace > 1){
  554.                 printf("metric not better: %s %lu\n",
  555.                  inet_ntoa(ep->target),ep->metric);
  556.             }
  557.         }
  558.     }
  559.     if(drop){
  560.         /* Switching to a better gateway; delete old entry */
  561.         if(Rip_trace){
  562.             printf("route drop [%s]/%u",
  563.              inet_ntoa(ep->target),bits);
  564.             if(rp != NULLROUTE)
  565.                 printf(" %s %s %lu",rp->iface->name,
  566.                  inet_ntoa(rp->gateway),rp->metric);
  567.             printf("\n");
  568.         }
  569.         rt_drop(ep->target,bits);
  570.     }
  571.     if(add){
  572.         /* Add a new entry */
  573.         interval = Rip_ttl;
  574.         for(rl=Rip_list; rl != NULLRL; rl = rl->next){
  575.             if(rl->iface == iface){
  576.                 interval = rl->interval * 4;
  577.                 break;
  578.             }
  579.         }
  580.         if(Rip_trace > 0){
  581.             printf("route add [%s]/%u %s",inet_ntoa(ep->target),
  582.              bits,iface->name);
  583.             printf(" [%s] %u\n",inet_ntoa(gateway),
  584.              (int)ep->metric);
  585.         }
  586.         rp = rt_add(ep->target,(unsigned) bits,gateway,iface,
  587.          (int) ep->metric,interval,0);
  588.     }
  589.     /* If the route changed, mark it for a triggered update */
  590.     if(trigger){
  591.         rp->flags |= RTTRIG;
  592.     }
  593. }
  594. /* Send a RIP request packet to the specified destination */
  595. int
  596. ripreq(dest,replyport)
  597. int32 dest;
  598. int16 replyport;
  599. {
  600.     struct mbuf *bp;
  601.     struct socket lsock,fsock;
  602.     char *cp;
  603.  
  604.     lsock.address = INADDR_ANY;
  605.     lsock.port = replyport;
  606.  
  607.     /* if we were given a valid dest addr, ask it (the routers on that net)
  608.      * for a default gateway
  609.      */
  610.     if(dest == 0)
  611.         return 0;
  612.  
  613.     fsock.address = dest;
  614.     fsock.port = RIP_PORT;
  615.  
  616.     /* Send out one RIP Request packet as a broadcast to 'dest'  */
  617.     if((bp = alloc_mbuf(RIPHEADER + RIPROUTE)) == NULLBUF)
  618.         return -1;
  619.  
  620.     cp = putheader(bp->data,RIPCMD_REQUEST,RIPVERSION);
  621.     cp = putentry(cp,0,0L,RIP_INFINITY);
  622.     bp->cnt = RIPHEADER + RIPROUTE;
  623.     send_udp(&lsock, &fsock,0,0,bp,bp->cnt,0,0);
  624.     Rip_stat.output++;
  625.     return 0;
  626. }
  627.  
  628. /* Write the header of a RIP packet */
  629. static char *
  630. putheader(cp,command,version)
  631. register char *cp;
  632. char command;
  633. char version;
  634. {
  635.     *cp++ = command;
  636.     *cp++ = version;
  637.     return put16(cp,0);
  638. }
  639.  
  640. /* Write a single entry into a rip packet */
  641. static char *
  642. putentry(cp,fam,target,metric)
  643. register char *cp;
  644. int16 fam;
  645. int32 target;
  646. int32 metric;
  647. {
  648.     cp = put16(cp,fam);
  649.     cp = put16(cp,0);
  650.     cp = put32(cp,target);
  651.     cp = put32(cp,0L);
  652.     cp = put32(cp,0L);
  653.     return put32(cp,metric);
  654. }
  655. /* Route timeout handler. If route has already been marked for deletion
  656.  * then delete it. Otherwise mark for deletion and restart timer.
  657.  */
  658. void
  659. rt_timeout(s)
  660. void *s;
  661. {
  662.     register struct route *rp = (struct route *)s;
  663.  
  664.     stop_timer(&rp->timer);
  665.     if(rp->metric < RIP_INFINITY){
  666.         rp->metric = RIP_INFINITY;
  667.         if(dur_timer(&rp->timer) == 0)
  668.             set_timer(&rp->timer,Rip_ttl*1000L);
  669.         /* wait 2/3 of timeout before garbage collect */
  670.         set_timer(&rp->timer,dur_timer(&rp->timer)*2/3);
  671.         rp->timer.func = (void *)rt_timeout;
  672.         rp->timer.arg = (void *)rp;
  673.         start_timer(&rp->timer);
  674.         /* Route changed; mark it for triggered update */
  675.         rp->flags |= RTTRIG;
  676.         rip_trigger();
  677.     } else {
  678.         rt_drop(rp->target,rp->bits);
  679.     }
  680. }
  681. #endif /* RIP */
  682.  
  683. void
  684. pullentry(ep,bpp)
  685. register struct rip_route *ep;
  686. struct mbuf **bpp;
  687. {
  688.     ep->addr_fam = pull16(bpp);
  689.     (void)pull16(bpp);
  690.     ep->target = pull32(bpp);
  691.     (void)pull32(bpp);
  692.     (void)pull32(bpp);
  693.     ep->metric = pull32(bpp);
  694. }
  695.  
  696.  
  697.